﻿#define TEXT_STRING
#undef TEXT_ROPE

// TEXT_STRING 编译开关开启表示当前元素存储字符串仍然是使用BCL的String字符串数组
// TEXT_ROPE 编译开关开启表示当前元素已经使用更便于字符串拼接的Rope数据结构存储字符串数据

namespace Acoris.Rendering
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Text;
    using Acoris.Media;
    using System.Numerics;

#if WIN2D
    using Microsoft.Graphics.Canvas.Brushes;
    using Microsoft.Graphics.Canvas.Text;
#endif

    /// <summary>
    /// 表示文本元素的抽象基类
    /// </summary>
    public abstract class TextElement : VisualElement
    {
        private string      m_text;
        protected object    LockObject;

        // CachedShadingIssue 的定义
        internal struct CachedShadingIssue
        {
            internal int index;
            internal int count;
            internal Brush brush;
        }

        internal Queue<CachedShadingIssue>      CacheIssue;
#if WIN2D
        internal ICanvasBrush                   ForegroundBrush;
        internal CanvasTextLayout               TextLayout;
        internal CanvasTextFormat               TextFormat;        
#endif

        /// <summary>
        /// 初始化文本元素
        /// </summary>
        protected TextElement()
        {
            LockObject = new object();
            CacheIssue = new Queue<CachedShadingIssue>();
        }

        #region Method

        /// <summary>
        /// 处理并释放资源
        /// </summary>
        public override void Dispose()
        {
            m_text = null;
            LockObject = null;
#if WIN2D
            ForegroundBrush?.Dispose();
            TextLayout?.Dispose();
            TextFormat?.Dispose();
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string GetText()
        {
#if TEXT_STRING
            return m_text;
#elif TEXT_ROPE
            return null;
#endif
        }


        /// <summary>
        /// 执行一次着色缓存过程
        /// </summary>
        /// <param name="indexCharacter">需要着色的开始位置</param>
        /// <param name="count">着色的字符数量</param>
        /// <param name="brush">要附加的颜色</param>
        public void Shading(int indexCharacter, int count, Brush brush)
        {
            // shading operation would not affect the rendering immediately
            // the operation will create a new cache issue into the shading queue
            // and there will be evaluate in next drawing call
            Debug.Assert(indexCharacter >= 0 && indexCharacter < this.Length);
            Debug.Assert(indexCharacter + count <= this.Length);
            Debug.Assert(brush != null);

            // shading operation should ensure thread-safe
            lock (LockObject)
            {
                CacheIssue.Enqueue(new CachedShadingIssue { index = indexCharacter, count = count, brush = brush });
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <param name="hasUnderline"></param>
        public void SetUnderline(int index,int count,bool hasUnderline)
        {
            Debug.Assert(index > -1);
            Debug.Assert(index + count <= this.Length);
#if WIN2D
            TextLayout.SetUnderline(index, count, hasUnderline);
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="index"></param>
        /// <param name="count"></param>
        /// <param name="hasStrikethrough"></param>
        public void SetStrikethrough(int index,int count,bool hasStrikethrough)
        {
            Debug.Assert(index > -1);
            Debug.Assert(index + count <= this.Length);            
#if WIN2D
            TextLayout.SetStrikethrough(index, count, hasStrikethrough);
#endif
        }

        #endregion

        #region Property

        /// <summary>
        /// 获取或设置当前字符元素的字符串
        /// </summary>
        public string Text {
            get {
                lock (LockObject)
                {
#if TEXT_STRING
                    return m_text;
#endif
#if TEXT_ROPE
                    return null;
#endif
                }
            }
            set {
#if WIN2D
                TextLayout?.Dispose();
#endif
#if TEXT_STRING
                m_text = SetUncacheResult(value);
#endif

#if TEXT_ROPE
#endif
            }
        }

        /// <summary>
        /// 获取当前文本元素的文本字符串长度
        /// </summary>
        public int Length {
            get {
                return (Text?.Length) ?? 0;
            }
        }

        #endregion

        #region Override

        /// <summary>
        /// 获取与当前对象等价的字符串形式
        /// </summary>
        /// <returns>返回与当前对象等价的字符串形式</returns>
        public override string ToString()
        {
            return Text;
        }

        /// <summary>
        /// 获取当前对象的哈希值
        /// </summary>
        /// <returns>返回当前对象的哈希值</returns>
        public override int GetHashCode()
        {
            return base.GetHashCode() ^ LockObject.GetHashCode() + (m_text?.Length ?? 0);
        }
        #endregion

    }
}
